#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <winsock2.h>
#include <ws2tcpip.h>              //  inet_pton is in this header for modern Windows
#pragma comment(lib, "ws2_32.lib") // Link with the Winsock library

#define SERVER_IP "127.0.0.1"
#define PORT 12345
#define FRAME_HEADER 0x5753

// 定义协议数据结构
typedef struct
{
    uint16_t frameHeader;
    uint8_t frameType;
    uint16_t dataFrameLength;
    uint64_t deviceSN;
    uint64_t timestamp;
    uint8_t dataItemCount;
    uint8_t *dataItems;
    uint8_t rollingCheck;
    uint8_t checksum;
} ProtocolPacket;

// 生成协议数据包
int generatePacket(ProtocolPacket *packet, uint8_t *buffer, size_t *buffer_len)
{
    size_t offset = 0;

    // 写入帧头
    buffer[offset++] = packet->frameHeader & 0xFF;
    buffer[offset++] = (packet->frameHeader >> 8) & 0xFF;

    // 写入帧类型
    buffer[offset++] = packet->frameType;

    // 写入数据帧长度
    buffer[offset++] = packet->dataFrameLength & 0xFF;
    buffer[offset++] = (packet->dataFrameLength >> 8) & 0xFF;

    // 写入采集设备编号
    for (int i = 0; i < 8; i++)
    {
        buffer[offset++] = (packet->deviceSN >> (8 * i)) & 0xFF;
    }

    // 写入时间戳
    for (int i = 0; i < 8; i++)
    {
        buffer[offset++] = (packet->timestamp >> (8 * i)) & 0xFF;
    }

    // 写入数据项数量
    buffer[offset++] = packet->dataItemCount;

    // 写入数据项内容
    if (packet->dataItems != NULL)
    {
        memcpy(&buffer[offset], packet->dataItems, packet->dataItemCount * 10);
        offset += packet->dataItemCount * 10;
    }

    // 写入滚动校验
    buffer[offset++] = packet->rollingCheck;

    // 计算并写入累加校验
    uint8_t checksum = 0;
    for (size_t i = 0; i < offset - 1; i++)
    { // 不包括checksum本身
        checksum += buffer[i];
    }
    buffer[offset++] = checksum;

    *buffer_len = offset;
    return 0;
}

// 客户端主函数
int main()
{
    printf("Program started\n");
    WSADATA wsaData;
    int client_fd;
    struct sockaddr_in server_addr;
    uint8_t buffer[1024];
    size_t buffer_len;

    // 初始化Winsock库
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        perror("WSAStartup failed");
        return 1;
    }
    printf("Winsock initialized\n");
    // 创建 socket
    if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("Socket creation failed");
        WSACleanup();
        return 1;
    }

    // 配置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0)
    {
        perror("Invalid address");
        closesocket(client_fd); // 使用closesocket
        WSACleanup();
        return 1;
    }

    // 连接服务器
    if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        perror("Connection failed");
        closesocket(client_fd); // 使用closesocket
        WSACleanup();
        return 1;
    }

    // 构造协议数据包
    ProtocolPacket packet;
    packet.frameHeader = FRAME_HEADER;
    packet.frameType = 0x01;
    packet.dataFrameLength = 63;
    packet.deviceSN = 610100122060001L;
    packet.timestamp = 0L;
    packet.dataItemCount = 2;

    // 数据项内容（示例数据）
    uint8_t dataItems[] = {
        0x44, 0x2F, 0xE1, 0xA4, 0x5C, 0x97, 0x52, 0x24, 0x01, 0x00,
        0x45, 0x2F, 0x71, 0x3D, 0x52, 0x41, 0x47, 0x2F, 0x00, 0x00};
    packet.dataItems = dataItems;
    packet.rollingCheck = 198;
    packet.checksum = 0;

    // 生成数据包
    if (generatePacket(&packet, buffer, &buffer_len) != 0)
    {
        fprintf(stderr, "Generate packet failed\n");
        closesocket(client_fd);
        WSACleanup();
        return 1;
    }

    // 发送数据包
    if (send(client_fd, buffer, buffer_len, 0) == -1)
    {
        perror("Send failed");
        closesocket(client_fd);
        WSACleanup();
        return 1;
    }

    printf("Packet sent to server.\n");

    // 关闭连接
    closesocket(client_fd);
    WSACleanup();

    return 0;
}